package com.sc.nft.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.*;
import com.sc.nft.controller.request.IdRequest;
import com.sc.nft.controller.vo.*;
import com.sc.nft.dao.*;
import com.sc.nft.dto.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.ScrollShopVO;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.UserCollectionFreezingStatusEnum;
import com.sc.nft.enums.WantBuyOrderStatusEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.ScrollWantBuyService;
import com.sc.nft.service.ScrollWantSellService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import com.sc.nft.util.OrderNoUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/scroll/shop")
@Api(tags = "卷轴商店控制器")
public class ScrollShopController {

    private final ScrollShopDao scrollShopDao;
    private final UserCollectionDao userCollectionDao;
    private final StaticDataDao staticDataDao;
    private final ScrollConfigDao scrollConfigDao;
    private final ScrollWantBuyService scrollWantBuyService;
    private final ScrollWantSellService scrollWantSellService;
    private final ScrollWantBuyDao scrollWantBuyDao;
    private final UserRelevanceDao userRelevanceDao;
    private final EquityPropsDao equityPropsDao;
    private final Redisson redisson;
    private final RedisTemplate redisTemplate;
    private final SecondEquityPropsOrderDao secondEquityPropsOrderDao;
    private final UserEquityPropsDao userEquityPropsDao;
    private final ScrollWantSellDao scrollWantSellDao;

    @ApiOperation(value = "获取店铺信息", notes = "获取店铺信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getShopInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<ScrollShopVO> getShopInfo() {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }
        ScrollShopVO scrollShopVO = new ScrollShopVO();

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return Result.fail(ErrorCode.SHOP_FREEZE);
            }
            scrollShopVO.setShopNum(scrollShop.getShopNum());
            scrollShopVO.setShopName(scrollShop.getShopName());
        }else{
            UserCollection userCollection = userCollectionDao.getMinNumCanUse(UserPool.getUser().getId(), Long.parseLong(openShop.getValue()));
            if(ObjectUtil.isEmpty(userCollection)){
                return Result.fail("店铺无法使用");
            }
            scrollShopVO.setShopNum(userCollection.getNumbering());
        }
        return Result.success(scrollShopVO);
    }


    @ApiOperation(value = "设置店铺名称", notes = "设置店铺名称", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/setShopName", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result setShopName(@Valid @RequestBody NameRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }
        UserCollection userCollection = userCollectionDao.getMinNumCanUse(UserPool.getUser().getId(), Long.parseLong(openShop.getValue()));
        if(ObjectUtil.isNull(userCollection)){
            return Result.fail("尚未开启店铺");
        }
        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            return Result.fail("您已开启过店铺了");
        }
        if(scrollShopDao.checkNameExists(request.getName())){
            return Result.fail("该名称已存在");
        }
        scrollShop = new ScrollShop();
        scrollShop.setShopName(request.getName());
        scrollShop.setUserCollectionId(userCollection.getId());
        scrollShop.setShopNum(userCollection.getNumbering());
        scrollShop.setUserId(UserPool.getUser().getId());
        scrollShop.setDealCount(0);
        scrollShop.setStatus(true);
        scrollShop.setFreezeStatus(false);
        scrollShop.insert();
        userCollection.setFreezingStatus(UserCollectionFreezingStatusEnum.OPEN_SHOP);
        userCollection.updateById();
        return Result.success();
    }


    @ApiOperation(value = "发布求购", notes = "发布求购", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/postPurchase", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result postPurchase(@Valid @RequestBody PostPurchaseRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return Result.fail(ErrorCode.SHOP_FREEZE);
            }
        }else{
            return Result.fail("尚未开启店铺");
        }
        ScrollConfig config = scrollConfigDao.getConfig();
        if(NumberUtil.isGreater(config.getBuyMinPrice(),request.getUnitPrice())||NumberUtil.isLess(config.getBuyMaxPrice(),request.getUnitPrice())){
            return Result.fail(StrUtil.format("求购金额须在{}-{}之间",config.getBuyMinPrice(),config.getBuyMaxPrice()));
        }
        if(config.getBuyMinCount().intValue()> request.getWantBuyCount().intValue()||config.getBuyMaxCount().intValue()<request.getWantBuyCount().intValue()){
            return Result.fail(StrUtil.format("求购数量须在{}-{}之间",config.getBuyMinCount(),config.getBuyMaxCount()));
        }
        Integer count = scrollWantBuyDao.getCountByShopId(scrollShop.getId());
        if(count>=config.getBuyOrderMaxCount()){
            return Result.fail(ErrorCode.WANT_BUY_LIMIT);
        }
        ScrollWantBuy scrollWantBuy = new ScrollWantBuy();
        scrollWantBuy.setShopId(scrollShop.getId());
        scrollWantBuy.setShopUserId(UserPool.getUser().getId());
        scrollWantBuy.setStatus(WantBuyOrderStatusEnum.WAIT_PAY);
        scrollWantBuy.setWantBuyCount(request.getWantBuyCount());
        scrollWantBuy.setOrderNo(OrderNoUtil.getOrderNo());
        scrollWantBuy.setCostPrice(BigDecimal.ZERO);
        scrollWantBuy.setBuyCount(0);
        scrollWantBuy.setRefundAmount(BigDecimal.ZERO);
        scrollWantBuy.setSumPrice(request.getUnitPrice().multiply(BigDecimal.valueOf(request.getWantBuyCount())));
        scrollWantBuy.setSurplusPrice(scrollWantBuy.getSumPrice());
        scrollWantBuy.setUnitPrice(request.getUnitPrice());
        scrollWantBuy.insert();
        return Result.success(scrollWantBuy.getId());
    }

    @ApiOperation(value = "求购单关闭", notes = "求购单关闭", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantBuyClose", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result wantBuyClose(@Valid @RequestBody CloseOrderRequest request) {
        RLock lock = redisson.getLock(RedisKeyEnum.SCROLL_SHOP_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                scrollWantBuyService.closeWantBuyOrder(request.getId(),UserPool.getUser(),request.getDealPassword());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "我的求购单列表", notes = "我的求购单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myWantBuyPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MyWantBuyVO> myWantBuyPage(@Valid @RequestBody PageRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return PageResult.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return PageResult.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return PageResult.fail(ErrorCode.SHOP_FREEZE);
            }
        }else{
            return PageResult.fail("尚未开启店铺");
        }
        List<MyWantBuyVO> result = Lists.newArrayList();
        Page<ScrollWantBuy> scrollWantBuyPage = scrollWantBuyService.myWantBuyPage(UserPool.getUser(), request.toMp());
        Page<MyWantBuyVO> page = new Page<>(scrollWantBuyPage.getCurrent(),scrollWantBuyPage.getSize(),scrollWantBuyPage.getTotal());
        StaticData equityPropsId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityPropsId.getValue()));
        for (ScrollWantBuy record : scrollWantBuyPage.getRecords()) {
            MyWantBuyVO myWantBuyVO = new MyWantBuyVO();
            myWantBuyVO.setId(record.getId());
            myWantBuyVO.setName(eq.getFirstTitle());
            myWantBuyVO.setImage(eq.getCreationContent());
            myWantBuyVO.setBuyCount(record.getBuyCount());
            myWantBuyVO.setSumCount(record.getWantBuyCount());
            myWantBuyVO.setCostPrice(record.getCostPrice().toPlainString());
            myWantBuyVO.setSurplusPrice(record.getSurplusPrice().toPlainString());
            myWantBuyVO.setSumPrice(record.getSumPrice().toPlainString());
            myWantBuyVO.setUnitPrice(record.getUnitPrice().toPlainString());
            myWantBuyVO.setCreateTime(record.getCreateTime());
            myWantBuyVO.setStatus(record.getStatus());
            result.add(myWantBuyVO);
        }
        page.setRecords(result);
        return PageResult.success(page);
    }


    @ApiOperation(value = "发布出售", notes = "发布出售", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/postSells", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result postSells(@Valid @RequestBody PostSellRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }

        if(!StrUtil.equals(request.getDealPassword(),UserPool.getUser().getTransactionPassword())){
            return Result.fail(ErrorCode.PAYMENT_PASSWORD_WAS_ENTERED_INCORRECTLY);
        }
        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return Result.fail(ErrorCode.SHOP_FREEZE);
            }
        }else{
            return Result.fail("尚未开启店铺");
        }
        StaticData equityId = staticDataDao.getByType("scroll_props_id");
        RLock lock = redisson.getLock(RedisKeyEnum.SCROLL_POST_SELL_ORDER.getKey() + UserPool.getUser().getId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                scrollWantSellService.postSell(UserPool.getUser(),scrollShop,Long.parseLong(equityId.getValue()),request.getUnitPrice(),request.getWantSellCount());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }

        return Result.success();
    }

    @ApiOperation(value = "关闭出售订单", notes = "关闭出售订单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/closeSellsOrder", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result closeSellsOrder(@Valid @RequestBody CloseOrderRequest request) {
        RLock lock = redisson.getLock(RedisKeyEnum.SCROLL_SHOP_SELL_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                scrollWantSellService.closeWantSellOrder(request.getId(),UserPool.getUser(),request.getDealPassword());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "用户购买", notes = "用户购买", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/userBuyShopOrder", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantSellOrderDTO> userBuyShopOrder(@Valid @RequestBody UserBuyShopOrderRequest request) {
        if (!UserPool.getUser().getIsSm()) {
            return Result.fail("请先完成实名认证");

        }
        ScrollConfig config = scrollConfigDao.getConfig();
        if(request.getCount()>20){
            return Result.fail("单次购买数量不能超过20单");
        }
        String lockKey = StrUtil.format("{}{}", RedisKeyEnum.SECOND_USER_LOCK.getKey(), UserPool.getUser().getId());
        Boolean b = redisTemplate.hasKey(lockKey);
        if (b) {
            Integer lockSum = Convert.toInt(redisTemplate.opsForValue().get(lockKey));
            if (lockSum >= 3) {
                throw new GlobalRunTimeException(ErrorCode.ARE_MORE_THAN_3_UNPAID_ORDERS_ON_THE_DAY_WHICH_WILL_BE_AUTOMATICALLY_CANCELLED);
            }
        }
        WantSellOrderDTO dto =null;
        RLock lock = redisson.getLock(RedisKeyEnum.SCROLL_SHOP_SELL_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                dto = scrollWantSellService.userBuyShopOrder(request.getId(),UserPool.getUser(),request.getCount());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success(dto);
    }


    @ApiOperation(value = "获取卷轴数量", notes = "获取卷轴数量", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getCount", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetScrollCountVO> getCount() {
        ScrollConfig config = scrollConfigDao.getConfig();
        StaticData equityPropsId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityPropsId.getValue()));
        GetScrollCountVO getScrollCountVO = new GetScrollCountVO();
        getScrollCountVO.setName(eq.getFirstTitle());
        getScrollCountVO.setImage(eq.getCreationContent());
        getScrollCountVO.setHoldCount(userEquityPropsDao.getCanUseCountByEquityIdAndUserId(Long.parseLong(equityPropsId.getValue()), UserPool.getUser().getId()));
        getScrollCountVO.setCanSellCount(Math.max(userEquityPropsDao.getHavingCountByUserId(eq.getId(),UserPool.getUserId())-config.getSalesFreezeCount(),0));
        return Result.success(getScrollCountVO);
    }


    @ApiOperation(value = "获取配置", notes = "获取配置", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getConfig", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<ScrollConfigVO> getConfig() {
        ScrollConfig config = scrollConfigDao.getConfig();
        ScrollConfigVO scrollConfigVO = new ScrollConfigVO();
        scrollConfigVO.setSalesMinPrice(config.getSalesMinPrice().toPlainString());
        scrollConfigVO.setSalesMaxPrice(config.getSalesMaxPrice().toPlainString());
        scrollConfigVO.setSalesMinCount(config.getSalesMinCount());
        scrollConfigVO.setSalesMaxCount(config.getSalesMaxCount());
        scrollConfigVO.setBuyMinPrice(config.getBuyMinPrice().toPlainString());
        scrollConfigVO.setBuyMaxPrice(config.getBuyMaxPrice().toPlainString());
        scrollConfigVO.setBuyMinCount(config.getBuyMinCount());
        scrollConfigVO.setBuyMaxCount(config.getBuyMaxCount());
        scrollConfigVO.setInDaoFee(config.getInDaoFee().toPlainString());
        scrollConfigVO.setInDaoAmount(config.getInDaoAmount().toPlainString());
        scrollConfigVO.setSalesFeeRatio(config.getSalesFeeRatio().toPlainString());
        scrollConfigVO.setSalesMinFeeAmount(config.getSalesMinFeeAmount().toPlainString());
        scrollConfigVO.setBuyOrderMaxCount(config.getBuyOrderMaxCount());
        scrollConfigVO.setSalesOrderMaxCount(config.getSalesOrderMaxCount());
        scrollConfigVO.setSalesFreezeCount(config.getSalesFreezeCount());
        return Result.success(scrollConfigVO);
    }

    @ApiOperation(value = "我的求购单详情", notes = "我的求购单详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantBuyDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<MyWantBuyVO> wantBuyPage(@Valid @RequestBody IdRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
        }else{
            return Result.fail("尚未开启店铺");
        }
        ScrollWantBuy wantBuy = scrollWantBuyDao.getById(request.getId());
        if(ObjectUtil.isNull(wantBuy)||wantBuy.getShopUserId().longValue()!=UserPool.getUser().getId()){
            return Result.fail("未找到求购订单");
        }
        StaticData equityId = staticDataDao.getByType("scroll_props_id");
        EquityProps equityProps = equityPropsDao.getById(Long.parseLong(equityId.getValue()));
        MyWantBuyVO myWantBuyVO = new MyWantBuyVO();
        myWantBuyVO.setId(wantBuy.getId());
        myWantBuyVO.setStatus(wantBuy.getStatus());
        myWantBuyVO.setCreateTime(wantBuy.getCreateTime());
        myWantBuyVO.setName(equityProps.getFirstTitle());
        myWantBuyVO.setImage(equityProps.getCreationContent());
        myWantBuyVO.setBuyCount(wantBuy.getBuyCount());
        myWantBuyVO.setUnitPrice(wantBuy.getUnitPrice().toPlainString());
        myWantBuyVO.setCostPrice(wantBuy.getCostPrice().toPlainString());
        myWantBuyVO.setSumPrice(wantBuy.getSumPrice().toPlainString());
        myWantBuyVO.setRefundAmount(wantBuy.getRefundAmount().toPlainString());
        myWantBuyVO.setSurplusPrice(wantBuy.getSurplusPrice().toPlainString());
        myWantBuyVO.setSumCount(wantBuy.getWantBuyCount());
        return Result.success(myWantBuyVO);
    }

    @ApiOperation(value = "求购单信息", notes = "求购单信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantBuyInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<WantBuyInfoVO> wantBuyInfo(@Valid @RequestBody IdRequest request) {

        ScrollWantBuy wantBuy = scrollWantBuyDao.getById(request.getId());
        if(ObjectUtil.isNull(wantBuy) ){
            return Result.fail("未找到求购订单");
        }
        StaticData equityId = staticDataDao.getByType("scroll_props_id");
        EquityProps equityProps = equityPropsDao.getById(Long.parseLong(equityId.getValue()));
        WantBuyInfoVO wantBuyInfoVO = new WantBuyInfoVO();
        wantBuyInfoVO.setName(equityProps.getFirstTitle());
        wantBuyInfoVO.setImage(equityProps.getCreationContent());
        wantBuyInfoVO.setHaveCount(userEquityPropsDao.getHavingCountByUserId(equityProps.getId(),UserPool.getUser().getId()));
        wantBuyInfoVO.setLastCount(wantBuy.getWantBuyCount()-wantBuy.getBuyCount());
        ScrollConfig config = scrollConfigDao.getConfig();
        Boolean isExistByUserIdAndRelevanceId = userRelevanceDao.getIsExistByUserIdAndRelevanceId(wantBuy.getShopUserId(), UserPool.getUser().getId());
        if(isExistByUserIdAndRelevanceId){
            BigDecimal fee = NumberUtil.max(config.getInDaoAmount(),wantBuy.getUnitPrice().multiply(config.getInDaoFee()).setScale(2,BigDecimal.ROUND_UP));
            wantBuyInfoVO.setServiceAmount(fee.toPlainString());
        }else{
            BigDecimal fee = NumberUtil.max(config.getOutDaoAmount(),wantBuy.getUnitPrice().multiply(config.getOutDaoRatio()).setScale(2,BigDecimal.ROUND_UP));
            wantBuyInfoVO.setServiceAmount(fee.toPlainString());
        }

        return Result.success(wantBuyInfoVO);
    }

    @ApiOperation(value = "求购单详情-成交记录", notes = "求购单详情-成交记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantBuyDetailRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MyWantBuyRecordVO> wantBuyDetailRecord(@Valid @RequestBody IdPageRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return PageResult.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return PageResult.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return PageResult.fail(ErrorCode.SHOP_FREEZE);
            }
        }else{
            return PageResult.fail("尚未开启店铺");
        }
        ScrollWantBuy wantBuy = scrollWantBuyDao.getById(request.getId());
        if(ObjectUtil.isNull(wantBuy)||wantBuy.getShopUserId().longValue()!=UserPool.getUser().getId()){
            return PageResult.fail("未找到求购订单");
        }
        return PageResult.success(secondEquityPropsOrderDao.getByWantBuyOrderId(request.getId(),request.toMp()));
    }


    @ApiOperation(value = "计算预计收益", notes = "计算预计收益", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/calExpectIncome", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<ExpectIncomeVO> calExpectIncome(@Valid @RequestBody SellPurchaseRequest request) {
        ScrollWantBuy wantBuy = scrollWantBuyDao.getById(request.getWantBuyOrderId());
        if(ObjectUtil.isNull(wantBuy)){
            return Result.fail("未找到求购单");
        }
        if(wantBuy.getStatus()!=WantBuyOrderStatusEnum.IN_BUY){
            return Result.fail("求购单状态不正确");
        }
        ScrollConfig config = scrollConfigDao.getConfig();
        Boolean isExistByUserIdAndRelevanceId = userRelevanceDao.getIsExistByUserIdAndRelevanceId(wantBuy.getShopUserId(), UserPool.getUser().getId());
        ExpectIncomeVO expectIncomeVO = new ExpectIncomeVO();
        expectIncomeVO.setCount(request.getWantSellCount());
        expectIncomeVO.setUnitPrice(request.getUnitPrice().setScale(2, RoundingMode.HALF_UP).toPlainString());
        expectIncomeVO.setSumPrice(request.getUnitPrice().multiply(BigDecimal.valueOf(request.getWantSellCount())).toPlainString());
        BigDecimal sumFee = BigDecimal.ZERO;
        if(isExistByUserIdAndRelevanceId){
            BigDecimal fee = NumberUtil.max(config.getInDaoAmount(),request.getUnitPrice().multiply(config.getInDaoFee()));
            expectIncomeVO.setUnitFee(fee.toPlainString());
            sumFee=fee.multiply(BigDecimal.valueOf(request.getWantSellCount())).setScale(2, RoundingMode.HALF_UP);
        }else{
            BigDecimal fee = NumberUtil.max(config.getOutDaoAmount(),request.getUnitPrice().multiply(config.getOutDaoRatio()));
            expectIncomeVO.setUnitFee(fee.toPlainString());
            sumFee=fee.multiply(BigDecimal.valueOf(request.getWantSellCount())).setScale(2, RoundingMode.HALF_UP);
        }
        expectIncomeVO.setSumFee(sumFee.toPlainString());
        expectIncomeVO.setExpectIncomePrice(request.getUnitPrice().multiply(BigDecimal.valueOf(request.getWantSellCount())).subtract(sumFee).setScale(2, RoundingMode.HALF_UP).toPlainString());
        return Result.success(expectIncomeVO);
    }



    @ApiOperation(value = "求购单列表", notes = "求购单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantBuyPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantBuyDTO> wantBuyPage(@Valid @RequestBody WantBuyPageRequest request) {
        Page<WantBuyDTO> wantBuyDTOPage = scrollWantBuyService.wantBuyPage(UserPool.getUser().getId(), request.getShopId(), request.getInDao(), request.toMp());
        StaticData equityPropsId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityPropsId.getValue()));
        ScrollConfig config = scrollConfigDao.getConfig();

        for (WantBuyDTO record : wantBuyDTOPage.getRecords()) {
            record.setName(eq.getFirstTitle());
            record.setImage(eq.getCreationContent());
            if(userRelevanceDao.getIsExistByUserIdAndRelevanceId(record.getShopUserId(),UserPool.getUser().getId())){
                record.setFee(config.getInDaoFee().multiply(BigDecimal.valueOf(100)).setScale(0,BigDecimal.ROUND_HALF_UP).toPlainString());
            }else{
                record.setFee(config.getOutDaoRatio().multiply(BigDecimal.valueOf(100)).setScale(0,BigDecimal.ROUND_HALF_UP).toPlainString());
            }
        }
        return PageResult.success(wantBuyDTOPage);
    }


    @ApiOperation(value = "出售单列表", notes = "出售单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/wantSellPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<WantSellDTO> wantSellPage(@Valid @RequestBody WantSellPageRequest request) {
        StaticData equityId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityId.getValue()));
        ScrollConfig config = scrollConfigDao.getConfig();
        Page<WantSellDTO> wantSellDTOPageResult = scrollWantSellService.wantSellPage(request.getShopId(), request.toMp());
        for (WantSellDTO record : wantSellDTOPageResult.getRecords()) {
            record.setName(eq.getFirstTitle());
            record.setImage(eq.getCreationContent());
        }
        return PageResult.success(wantSellDTOPageResult);
    }

    @ApiOperation(value = "卖给店铺", notes = "卖给店铺", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/sellToShop", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result sellToShop(@Valid @RequestBody SellToShopRequest request) {
        DateTime now = DateTime.now();
        UserInfo user = UserPool.getUser();
        if(now.getField(DateField.HOUR_OF_DAY)<17){
            return Result.fail("每日可出售时间为17点00分至23点59");
        }
        RLock lock = redisson.getLock(RedisKeyEnum.SCROLL_SHOP_ORDER.getKey() + request.getWantBuyOrderId());
        RLock userLock = redisson.getLock(RedisKeyEnum.USER_SCROLL_SHOP_ORDER.getKey() + user.getId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                boolean userLockRes = userLock.tryLock(10, TimeUnit.SECONDS);
                if(!userLockRes){
                    return Result.fail("请稍后重试!");
                }
                scrollWantBuyService.userSellToShop(request.getWantBuyOrderId(),request.getSellCount(),user,request.getDealPassword());

            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("当前人数过多，请稍后再试");
        } finally {
            lock.unlock();
            userLock.unlock();
        }
        return Result.success( );
    }

    @ApiOperation(value = "查询店铺", notes = "查询店铺", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/findShop", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult findShop(@Valid @RequestBody FindShopRequest request) {
        Page<ScrollShop> page = scrollShopDao.findBykeyWord(request.getKeyword(),request.toMp());
        Page<ScrollShopVO> result = new Page<>(page.getCurrent(),page.getSize(),page.getTotal());

        List<ScrollShopVO> scrollShopVOS = Lists.newArrayList();
        for (ScrollShop scrollShop : page.getRecords()) {
            ScrollShopVO scrollShopVO = new ScrollShopVO();
            scrollShopVO.setShopId(scrollShop.getId());
            scrollShopVO.setShopName(scrollShop.getShopName());
            scrollShopVO.setShopNum(scrollShop.getShopNum());
            scrollShopVO.setInDao(userRelevanceDao.getIsExistByUserIdAndRelevanceId(scrollShop.getUserId(),UserPool.getUser().getId()));
            scrollShopVOS.add(scrollShopVO);
        }
        result.setRecords(scrollShopVOS);
        return PageResult.success(result);
    }

    @ApiOperation(value = "我的出售单列表", notes = "我的出售单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myWantSellPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MyWantSellVO> myWantSellPage(@Valid @RequestBody PageRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return PageResult.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return PageResult.fail("当前店铺服已关闭");
            }
            if(scrollShop.getFreezeStatus()){
                return PageResult.fail(ErrorCode.SHOP_FREEZE);
            }
        }else{
            return PageResult.fail("尚未开启店铺");
        }
        List<MyWantSellVO> result = Lists.newArrayList();
        ScrollConfig config = scrollConfigDao.getConfig();
        Page<ScrollWantSell> sellPage = scrollWantSellService.myWantSellPage(UserPool.getUser(), request.toMp());
        Page<MyWantSellVO> page = new Page<>(sellPage.getCurrent(),sellPage.getSize(),sellPage.getTotal());
        StaticData equityPropsId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityPropsId.getValue()));
        for (ScrollWantSell record : sellPage.getRecords()) {
            MyWantSellVO vo = new MyWantSellVO();
            vo.setId(record.getId());
            vo.setName(eq.getFirstTitle());
            vo.setImage(eq.getCreationContent());
            vo.setCreateTime(record.getCreateTime());
            vo.setSumCount(record.getWantSellCount());
            vo.setUnitPrice(record.getUnitPrice().toPlainString());
            vo.setSalesFeeAmount(record.getSalesFeeAmount().toPlainString());
            vo.setStatus(record.getStatus());
            vo.setFee(config.getSalesFeeRatio().toPlainString());
            vo.setMinFeeAmount(config.getSalesMinFeeAmount().toPlainString());
            vo.setSalesCount(record.getSalesCount());
            vo.setSalesPrice(record.getSalesPrice().toPlainString());
            vo.setIncomePrice(record.getSalesPrice().subtract(record.getSalesFeeAmount()).toPlainString());
            result.add(vo);
        }
        page.setRecords(result);
        return PageResult.success(page);
    }


    @ApiOperation(value = "我的出售单详情", notes = "我的出售单详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myWantSellDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<MyWantSellVO> myWantSellDetail(@Valid @RequestBody IdRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
        }else{
            return Result.fail("尚未开启店铺");
        }
        ScrollWantSell wantSell = scrollWantSellDao.getById(request.getId());
        if(ObjectUtil.isNull(wantSell)||wantSell.getShopUserId().longValue()!=UserPool.getUser().getId()){
            return Result.fail("未找发布出售订单");
        }
        StaticData equityId = staticDataDao.getByType("scroll_props_id");
        EquityProps eq = equityPropsDao.getById(Long.parseLong(equityId.getValue()));
        ScrollConfig config = scrollConfigDao.getConfig();
        MyWantSellVO vo = new MyWantSellVO();
        vo.setId(wantSell.getId());
        vo.setName(eq.getFirstTitle());
        vo.setImage(eq.getCreationContent());
        vo.setCreateTime(wantSell.getCreateTime());
        vo.setSumCount(wantSell.getWantSellCount());
        vo.setUnitPrice(wantSell.getUnitPrice().toPlainString());
        vo.setStatus(wantSell.getStatus());
        vo.setSalesFeeAmount(wantSell.getSalesFeeAmount().toPlainString());
        vo.setFee(config.getSalesFeeRatio().toPlainString());
        vo.setMinFeeAmount(config.getSalesMinFeeAmount().toPlainString());
        vo.setSalesCount(wantSell.getSalesCount());
        vo.setSalesPrice(wantSell.getSalesPrice().toPlainString());
        vo.setIncomePrice(wantSell.getSalesPrice().subtract(wantSell.getSalesFeeAmount()).toPlainString());
        return Result.success(vo);
    }

    @ApiOperation(value = "我的出售单详情-成交记录", notes = "我的出售单详情-成交记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myWantSellDetailRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<MyWantSellRecordVO> myWantSellDetailRecord(@Valid @RequestBody IdPageRequest request) {
        StaticData openShop = staticDataDao.getByType("scroll_shop_collection_id");
        if(ObjectUtil.isNull(openShop)||StrUtil.isBlank(openShop.getValue())){
            return Result.fail("尚未开启店铺");
        }

        ScrollShop scrollShop = scrollShopDao.getByUserId(UserPool.getUser().getId());
        if(ObjectUtil.isNotNull(scrollShop)){
            if(!scrollShop.getStatus()){
                return Result.fail("当前店铺服已关闭");
            }
        }else{
            return Result.fail("尚未开启店铺");
        }
        ScrollWantSell wantSell = scrollWantSellDao.getById(request.getId());
        if(ObjectUtil.isNull(wantSell)||wantSell.getShopUserId().longValue()!=UserPool.getUser().getId()){
            return Result.fail("未找发布出售订单");
        }

        return PageResult.success(secondEquityPropsOrderDao.getByWantSellOrderId(request.getId(),request.toMp()));
    }
}
